#include "Event.h"
#include "SharedPtr.h"
#include <stdexcept>

DEF_BEG_LIBTOOLS

CEvent::CEvent(bool status /*= false*/, bool reset /*= true*/)
{
	 _event = ShareApi::CreateEvent(status ? TRUE : FALSE, reset ? TRUE : FALSE);
	if (_event == 0) throw std::runtime_error("create event failed!");
}

CEvent::~CEvent()
{
	ShareApi::CloseEvent(_event);
	 _event = 0;
}

void CEvent::SetEvent(bool status)
{
	ShareApi::SetEvent(_event, status ? TRUE : FALSE);
}

wt_status CEvent::Wait(unsigned int pred)
{
	wt_status s = wt_notimeout;
	DWORD ret = ShareApi::WaitForSingleEvent(_event, pred);

	if (ret == WAIT_FAILED) s = wt_abort;
	else if (ret == WAIT_TIMEOUT) s = wt_timeout;

	return s;
}

wt_status CEvent::Wait_Forever()
{
	wt_status s = wt_notimeout;
	DWORD ret = ShareApi::WaitForSingleEvent(_event, INFINITE);

	if (ret == WAIT_FAILED) s = wt_abort;
	else if (ret == WAIT_TIMEOUT) s = wt_timeout;

	return s;
}

SYNCHANDLE CEvent::Handle() const
{
	return _event;
}

CWaitMultiEvent::CWaitMultiEvent(const std::vector<CEventBase*>& ves, bool waitall, unsigned int pred, wt_status& status, int *index /* = 0 */)
{
	SharedPtr<SYNCHANDLE> es(new SYNCHANDLE[ves.size()]);
	for(size_t i = 0; i < ves.size(); i++) es.Get()[i] = ves[i]->Handle();

	status = wt_notimeout;
	DWORD ret = ShareApi::WaitForMultipleEvents(es.Get(), (int)ves.size(), waitall ? TRUE : FALSE, pred);

	if (ret == WAIT_FAILED) status = wt_abort;
	else if (ret == WAIT_TIMEOUT) status = wt_timeout;
	else
	{
		if (index) *index = (int)ret;
	}
}

CWaitMultiEventForever::CWaitMultiEventForever(const std::vector<CEventBase*>& ves, bool waitall, wt_status& status, int *index /* = 0 */)
{
	CWaitMultiEvent(ves, waitall, INFINITE, status, index);
}

DEF_END_LIBTOOLS